package com.slipper.codeless.service;

import com.github.pagehelper.PageInfo;
import com.slipper.codeless.resolve.SqlBuilderFactory;
import com.slipper.codeless.resolve.SymbolUtil;
import com.slipper.codeless.resolve.delete.DeleteResolver;
import com.slipper.codeless.resolve.query.*;
import com.slipper.codeless.resolve.update.Update;
import com.slipper.codeless.resolve.update.UpdateResolver;
import com.slipper.common.bo.UserDetail;
import com.slipper.common.service.CommonService;
import com.slipper.constants.Constants;
import com.slipper.core.message.MessageUtil;
import com.slipper.core.message.Topic;
import com.slipper.datasource.DatasourceUtil;
import com.slipper.exception.CommonException;
import com.slipper.exception.ForbiddenException;
import com.slipper.system.codeless.bo.*;
import com.slipper.system.codeless.service.*;
import com.slipper.system.sequence.service.SequenceService;
import com.slipper.util.Tool;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;

@Component
public class CodelessService {
    @Resource
    public DataModelService dataModelService;
    @Resource
    public DataTableService dataTableService;
    @Resource
    public DataFieldService dataFieldService;
    @Resource
    public PageService pageService;
    @Resource
    public DatasourceService datasourceService;
    @Resource
    private CommonService commonService;
    @Resource
    public PageCompButtonUpdateService pageCompButtonUpdateService;
    @Resource
    public SequenceService sequenceService;
    @Resource
    public QueryResolver queryResolver;
    @Resource
    public UpdateResolver updateResolver;
    @Resource
    public DeleteResolver deleteResolver;

    public void checkPermit(UserDetail user, String... privilegeIds) {
        if (user == null) return;
        if (user.isSuperAdmin()) return;
        if (user.getPrivilegeList().isEmpty()) throw new ForbiddenException();

        for (String privilegeId : privilegeIds) {
            if (Tool.isBlank(privilegeId)) continue;

            if (user.getPrivilegeList().stream().noneMatch(item -> item.getPrivilegeId().equals(privilegeId))) {
                throw new ForbiddenException();
            }
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModelId 数据模型id
     * @param data        查询参数
     * @return 数据模型数据
     */
    public Map<String, Object> queryByParam(String dataModelId, Map<String, Object> data) {
        if (Tool.isBlank(dataModelId)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(dataModel, data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryOne(queryMap);
        } else {
            return DatasourceUtil.queryOne(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据数据模型数据主键id查询数据模型code对应的数据
     * @param dataModelId   数据模型id
     * @param dataId 数据模型数据主键id
     * @return 数据模型数据
     */
    public Map<String, Object> queryBy(String dataModelId, String dataId) {
        if (Tool.isBlank(dataModelId)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        DataFieldBO pkField = dataModel.getFieldList().stream()
                .filter(item -> Constants.YES.equals(item.getPrimaryKey()))
                .findFirst().orElse(null);
        if (pkField == null) throw new CommonException("数据模型未配置主键！");

        Map<String, Object> data = new HashMap<>();
        data.put(pkField.getFieldName(), dataId);
        Query query = queryResolver.resolve(dataModel, data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryOne(queryMap);
        } else {
            return DatasourceUtil.queryOne(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据数据模型数据主键id查询数据模型code对应的数据
     * @param code   数据模型编码
     * @param dataId 数据模型数据主键id
     * @return 数据模型数据
     */
    public Map<String, Object> queryByCode(String code, String dataId) {
        if (Tool.isBlank(code)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        DataFieldBO pkField = dataModel.getFieldList().stream()
                .filter(item -> Constants.YES.equals(item.getPrimaryKey()))
                .findFirst().orElse(null);
        if (pkField == null) throw new CommonException("数据模型未配置主键！");

        Map<String, Object> data = new HashMap<>();
        data.put(pkField.getFieldName(), dataId);
        Query query = queryResolver.resolve(dataModel, data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryOne(queryMap);
        } else {
            return DatasourceUtil.queryOne(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModelId 数据模型id
     * @param data        查询参数
     * @return 数据模型数据
     */
    public List<Map<String, Object>> queryList(String dataModelId, Map<String, Object> data) {
        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(dataModel, data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryList(queryMap);
        } else {
            return DatasourceUtil.queryList(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param code 数据模型编码
     * @param data 查询参数
     * @return 数据模型数据
     */
    public List<Map<String, Object>> queryListByCode(
            String code,
            Map<String, Object> data,
            Map<String, String> orderMap) {
        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(dataModel, data, orderMap);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryList(queryMap);
        } else {
            return DatasourceUtil.queryList(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModelId 数据模型id
     * @param dataMap 查询参数
     * @param orderMap 排序参数
     * @return 数据模型数据
     */
    public List<Map<String, Object>> queryList(
            String dataModelId,
            Map<String, Object> dataMap,
            Map<String, String> orderMap) {
        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(dataModel, dataMap, orderMap);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryList(queryMap);
        } else {
            return DatasourceUtil.queryList(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModel 数据模型id
     * @param data      查询参数
     * @return 数据模型数据
     */
    public List<Map<String, Object>> queryList(
            DataModelBO dataModel,
            List<PageCompFilterBO> filterList,
            List<PrivilegeBO> privilegeList,
            List<DataTableOrdinalBO> ordinalList,
            Map<String, Object> data) {
        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(
                null,
                dataModel,
                filterList,
                privilegeList,
                ordinalList,
                data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryList(queryMap);
        } else {
            return DatasourceUtil.queryList(query.getDatasourceId(), queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModelId 数据模型id
     * @param data        查询参数
     * @return 数据模型数据
     */
    public PageInfo<Map<String, Object>> queryPage(String dataModelId, Map<String, Object> data) {
        if (Tool.isBlank(dataModelId)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(dataModel, data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        int pageNumber = data.containsKey("pageNumber") ? (Integer) data.get("pageNumber") : 1;
        int pageSize = data.containsKey("pageSize") ? (Integer) data.get("pageSize") : 20;
        if (query.isLocal()) {
            return commonService.queryPage(pageNumber, pageSize, queryMap);
        } else {
            return DatasourceUtil.queryPage(query.getDatasourceId(), pageNumber, pageSize, queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModelId 数据模型id
     * @param data        查询参数
     * @return 数据模型数据
     */
    public PageInfo<Map<String, Object>> queryDistinctPage(String dataModelId, Map<String, Object> data) {
        if (Tool.isBlank(dataModelId)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        Query query = new Query();
        query.setTableName(dataModel.getCode());

        QueryField queryField = new QueryField();
        queryField.setTplContent("distinct ${value}");
        queryField.setOriginName((String) data.get("distinctName"));
        queryField.setTargetName((String) data.get("distinctName"));
        query.addQueryField(queryField);

        if (Tool.isNotBlank(data.get("filterValue"))) {
            Condition condition = new Condition();
            condition.setFieldName((String) data.get("filterName"));
            condition.setItemList(List.of(new ConditionItem("模糊", data.get("filterValue"))));
            query.addCondition(List.of(condition));
        }

        query.addSortField((String) data.get("distinctName"), "asc", 0);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        int pageNumber = data.containsKey("pageNumber") ? (Integer) data.get("pageNumber") : 1;
        int pageSize = data.containsKey("pageSize") ? (Integer) data.get("pageSize") : 20;
        if (query.isLocal()) {
            return commonService.queryPage(pageNumber, pageSize, queryMap);
        } else {
            return DatasourceUtil.queryPage(query.getDatasourceId(), pageNumber, pageSize, queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param code 数据模型id
     * @param data 查询参数
     * @return 数据模型数据
     */
    public PageInfo<Map<String, Object>> queryPageByCode(
            String code,
            Map<String, Object> data,
            Map<String, String> orderMap) {
        if (Tool.isBlank(code)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        Query query = queryResolver.resolve(dataModel, data, orderMap);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        int pageNumber = data.containsKey("pageNumber") ? (Integer) data.get("pageNumber") : 1;
        int pageSize = data.containsKey("pageSize") ? (Integer) data.get("pageSize") : 20;
        if (query.isLocal()) {
            return commonService.queryPage(pageNumber, pageSize, queryMap);
        } else {
            return DatasourceUtil.queryPage(query.getDatasourceId(), pageNumber, pageSize, queryMap);
        }
    }

    /**
     * 根据参数查询数据模型id对应的数据
     * @param dataModelId 数据模型id
     * @param data        查询参数
     * @return 数据模型数据
     */
    public PageInfo<Map<String, Object>> queryPage(
            PageCompBO pageComp,
            String dataModelId,
            List<PageCompFilterBO> filterList,
            List<PrivilegeBO> privilegeList,
            List<DataTableOrdinalBO> ordinalList,
            Map<String, Object> data) {
        if (Tool.isBlank(dataModelId)) throw new CommonException("参数错误！");

        DataModelBO dataModel = dataModelService.queryBy(dataModelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        int pageNumber = data.containsKey("pageNumber") ? (Integer) data.get("pageNumber") : 1;
        int pageSize = data.containsKey("pageSize") ? (Integer) data.get("pageSize") : 20;
        Query query = queryResolver.resolve(
                pageComp,
                dataModel,
                filterList,
                privilegeList,
                ordinalList,
                data);
        Map<String, Object> queryMap = SqlBuilderFactory.buildQueryMap(query);
        if (query.isLocal()) {
            return commonService.queryPage(pageNumber, pageSize, queryMap);
        } else {
            return DatasourceUtil.queryPage(query.getDatasourceId(), pageNumber, pageSize, queryMap);
        }
    }

    /**
     * 根据数据模型code保存对应的数据模型数据
     * @param tableId  数据表格ID
     * @param dataList 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int saveByDataTableId(String tableId, UserDetail user, List<Map<String, Object>> dataList) {
        DataTableBO dataTable = dataTableService.queryBy(tableId);
        if (dataTable == null) throw new CommonException("数据表格信息不存在！");

        DataModelBO dataModel = dataModelService.queryBy(dataTable.getModelId());
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许修改！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));

        List<Map<String, Object>> insertList = new ArrayList<>();
        List<Map<String, Object>> updateList = new ArrayList<>();
        for (Map<String, Object> data : dataList) {
            boolean isInsert = isInsert(dataModel, data);
            dataTable.getFieldList().forEach(tableField -> dataModel.getFieldList().stream()
                    .filter(dataField -> dataField.getId().equals(tableField.getFieldId()))
                    .findFirst()
                    .ifPresent(field -> checkDataField(field, data, dataModel.getFieldList(), isInsert)));
            Update update = updateResolver.resolve(dataModel, data, user);
            Map<String, Object> paramMap = SqlBuilderFactory.buildUpdateMap(update);
            if (update.isInsert()) {
                insertList.add(paramMap);
            } else {
                updateList.add(paramMap);
            }
        }

        int result = 0;
        if (!insertList.isEmpty()) {
            result += commonService.insert(insertList);
        }
        if (!updateList.isEmpty()) {
            result += commonService.update(updateList);
        }
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param id   数据模型code
     * @param data 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int saveByDataModelId(String id, UserDetail user, Map<String, Object> data, String buttonId) {
        return saveByDataModelId(id, user, data, buttonId, false);
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param id   数据模型code
     * @param data 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int saveByDataModelId(String id, UserDetail user, Map<String, Object> data, String buttonId, boolean isCopy) {
        DataModelBO dataModel = dataModelService.queryBy(id);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许修改！");

        List<PageCompButtonUpdateBO> updateList;
        if (Tool.isNotBlank(buttonId)) {
            updateList = pageCompButtonUpdateService.queryByButtonId(buttonId);
        } else {
            updateList = Collections.emptyList();
        }
        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        boolean isInsert = isInsert(dataModel, data, isCopy);
        dataModel.getFieldList().forEach(field -> {
            checkDataField(field, data, dataModel.getFieldList(), isInsert);
            if (isInsert) updateDefaultValue(field, data);
            convertValue(data, field, data.get(field.getFieldName()));
            updateList.stream()
                    .filter(item -> field.getId().equals(item.getFieldId()))
                    .findFirst()
                    .ifPresent(item -> convertValue(data, field, SymbolUtil.parse(item.getFieldValue()), false));
        });
        Update update = updateResolver.resolve(dataModel, data, user);
        int result;
        if (update.isInsert()) {
            result = commonService.insert(SqlBuilderFactory.buildUpdateMap(update));
        } else {
            result = commonService.update(SqlBuilderFactory.buildUpdateMap(update));
        }
        data.put(update.getPkIdName(), update.getPkIdValue());
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    private void convertValue(Map<String, Object> data, List<DataFieldBO> fieldList) {
        if (data.isEmpty() || fieldList.isEmpty()) return;
        fieldList.forEach(field -> convertValue(data, field, data.get(field.getFieldName())));
    }

    private void convertValue(Map<String, Object> data, DataFieldBO field, Object fieldValue) {
        convertValue(data, field, fieldValue, true);
    }

    private void convertValue(Map<String, Object> data, DataFieldBO field, Object fieldValue, boolean skillNull) {
        if (Tool.isBlank(fieldValue)) {
            if (!skillNull) {
                data.put(field.getFieldName(), null);
            }
            return;
        }

        Object dataValue;
        switch (field.getFieldType()) {
            case "整数" -> dataValue = Integer.parseInt(fieldValue.toString());
            case "小数" -> {
                try {
                    dataValue = new DecimalFormat("#0.#").parse(fieldValue.toString());
                } catch (ParseException e) {
                    throw new CommonException("小数【" + fieldValue + "】解释出错！", e);
                }
            }
            case "时间" -> dataValue = Long.parseLong(fieldValue.toString());
            default -> dataValue = fieldValue;
        }
        data.put(field.getFieldName(), dataValue);
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param id 数据模型code
     * @param dataList 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int saveByDataModelId(String id, UserDetail user, List<Map<String, Object>> dataList, String buttonId) {
        DataModelBO dataModel = dataModelService.queryBy(id);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许修改！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        List<PageCompButtonUpdateBO> updateList;
        if (Tool.isNotBlank(buttonId)) {
            updateList = pageCompButtonUpdateService.queryByButtonId(buttonId);
        } else {
            updateList = Collections.emptyList();
        }
        dataList.forEach(data -> {
            boolean isInsert = isInsert(dataModel, data);
            dataModel.getFieldList().forEach(field -> {
                checkDataField(field, data, dataModel.getFieldList(), isInsert);
                if (isInsert) updateDefaultValue(field, data);
                updateList.stream()
                        .filter(item -> field.getId().equals(item.getFieldId()))
                        .findFirst()
                        .ifPresent(item ->data.put(field.getFieldName(), SymbolUtil.parse(item.getFieldValue())));
            });
            Update update = updateResolver.resolve(dataModel, data, user);
            data.put(update.getPkIdName(), update.getPkIdValue());
            if (update.isInsert()) {
                commonService.insert(SqlBuilderFactory.buildUpdateMap(update));
            } else {
                commonService.update(SqlBuilderFactory.buildUpdateMap(update));
            }
        });

        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return 1;
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param code 数据模型code
     * @param data 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int insert(String code, UserDetail user, Map<String, Object> data, boolean trigger) {
        return execute(code, user, data, true, trigger);
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param code 数据模型code
     * @param data 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int update(String code, UserDetail user, Map<String, Object> data, boolean trigger) {
        return execute(code, user, data, false, trigger);
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param code 数据模型code
     * @param data 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int execute(String code, UserDetail user, Map<String, Object> data, boolean insert, boolean trigger) {
        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许修改！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        boolean isInsert = isInsert(dataModel, data);
        dataModel.getFieldList().forEach(field -> {
            checkDataField(field, data, dataModel.getFieldList(), isInsert);
            if (isInsert) updateDefaultValue(field, data);
        });
        Update update = updateResolver.resolve(dataModel, data, user, insert);

        int result;
        if (update.isInsert()) {
            result = commonService.insert(SqlBuilderFactory.buildUpdateMap(update), trigger);
        } else {
            result = commonService.update(SqlBuilderFactory.buildUpdateMap(update), trigger);
        }
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param code 数据模型code
     * @param user 当前用户
     * @param dataList 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int batchInsert(String code, UserDetail user, List<Map<String, Object>> dataList, boolean trigger) {
        return batchExecute(code, user, dataList, true, trigger);
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param code 数据模型code
     * @param user 当前用户
     * @param dataList 保存的数据模型数据
     * @return int > 0 保存成功，否则保存失败
     */
    public int batchUpdate(String code, UserDetail user, List<Map<String, Object>> dataList, boolean trigger) {
        return batchExecute(code, user, dataList, false, trigger);
    }

    /**
     * 根据数据模型id保存对应的数据模型数据
     * @param code 数据模型code
     * @param user 当前用户
     * @param dataList 保存的数据模型数据
     * @param insert true: 插入, false: 更新
     * @return int > 0 保存成功，否则保存失败
     */
    public int batchExecute(
            String code,
            UserDetail user,
            List<Map<String, Object>> dataList,
            boolean insert,
            boolean trigger) {
        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许修改！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));

        List<Map<String, Object>> updateList = new ArrayList<>();
        dataList.forEach(data -> {
            dataModel.getFieldList().forEach(field -> {
                checkDataField(field, data, dataModel.getFieldList(), insert);
                if (insert) updateDefaultValue(field, data);
            });
            convertValue(data, dataModel.getFieldList());
            Update update = updateResolver.resolve(dataModel, data, user, insert);
            updateList.add(SqlBuilderFactory.buildUpdateMap(update));
        });

        int result;
        if (insert) {
            result = commonService.insert(updateList, trigger);
        } else {
            result = commonService.update(updateList, trigger);
        }
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    private void checkDataField(DataFieldBO field, Map<String, Object> data, List<DataFieldBO> fieldList, boolean isInsert) {
        // 自动生成值
        Object fieldValue = data.get(field.getFieldName());
        if (Tool.isBlank(fieldValue)
                && Constants.YES.equals(field.getAutoCreate())
                && isInsert
                && DataFieldBO.FIELD_TYPE_VARCHAR.equals(field.getFieldType())) {
            data.put(field.getFieldName(), sequenceService.getNextSequenceById(field.getAutoSequenceId()));
            return;
        }

        if (!data.containsKey(field.getFieldName())) return;

        if (Tool.isBlank(fieldValue) && Constants.YES.equals(field.getRequired())) {
            throw new CommonException("字段【" + field.getFieldName() + "】不能为空！");
        }

        if (Tool.isBlank(fieldValue)) return;
        if (DataFieldBO.FIELD_TYPE_TEXT.equals(field.getFieldType())) return;

        if (DataFieldBO.FIELD_TYPE_VARCHAR.equals(field.getFieldType()) && Constants.YES.equals(field.getTrimBlank())) {
            fieldValue = fieldValue.toString().trim();
            data.put(field.getFieldName(), fieldValue);
        }

        if (DataFieldBO.FIELD_TYPE_RELATION.equals(field.getFieldType())
                && DataFieldBO.RELEVANCE_TYPE_EMP.equals(field.getRelevanceType())
                && fieldValue.toString().contains("@")) {
            String[] deptEmpId = fieldValue.toString().split("@");
            if (deptEmpId.length > 1) {
                fieldValue = deptEmpId[1];
                data.put(field.getFieldName(), fieldValue);
                fieldList.stream()
                        .filter(item -> field.getId().equals(item.getNativeFieldId()))
                        .findFirst()
                        .ifPresent(item -> data.put(item.getFieldName(), deptEmpId[0]));
            }
        }

        // 字符、整数、小数、日期、时间、图片、视频、附件、地图、大文本
        if ("时间,图片,视频,附件".contains(field.getFieldType()) && fieldValue.toString().length() > 20) {
            throw new CommonException(field.getFieldName() + "内容不正确！");
        } else if ("日期".contains(field.getFieldType())
                && field.getFieldSize() != null
                && fieldValue.toString().length() > field.getFieldSize()) {
            throw new CommonException("字段【" + field.getFieldName() + "】最大长度为：" + field.getFieldSize() + "！");
        } else if (DataFieldBO.FIELD_TYPE_RELATION.equals(field.getFieldType()) && fieldValue.toString().length() > 20) {
            if (field.getRelevanceType().contains(DataFieldBO.RELEVANCE_TYPE_DICT)) {
                throw new CommonException(field.getFieldName() + "字典键内容长度不允许超过20个字符！");
            } else {
                throw new CommonException(field.getFieldName() + "内容长度不允许超过20个字符！");
            }
        } else if ("整数、小数".contains(field.getFieldType())) {
            BigDecimal bigDecimal = new BigDecimal(fieldValue.toString());
            if (field.getMinValue() != null) {
                if ((Constants.YES.equals(field.getContainMinValue())
                        && bigDecimal.compareTo(new BigDecimal(field.getMinValue())) < 0)
                        || (!Constants.YES.equals(field.getContainMinValue())
                        && bigDecimal.compareTo(new BigDecimal(field.getMinValue())) <= 0)) {
                    String contain = (Constants.YES.equals(field.getContainMinValue()) ? "" : "不") + "包含";
                    throw new CommonException("字段【" + field.getFieldName() + "】"
                            + "最小值(" + contain + ")为："
                            + field.getMinValue() + "！");
                }
            }
            if (field.getMaxValue() != null) {
                if ((Constants.YES.equals(field.getContainMinValue())
                        && bigDecimal.compareTo(new BigDecimal(field.getMaxValue())) > 0)
                        || (!Constants.YES.equals(field.getContainMinValue())
                        && bigDecimal.compareTo(new BigDecimal(field.getMaxValue())) >= 0)) {
                    String contain = (Constants.YES.equals(field.getContainMinValue()) ? "" : "不") + "包含";
                    throw new CommonException("字段【" + field.getFieldName() + "】"
                            + "最大值(" + contain + ")为："
                            + field.getMaxValue() + "！");
                }
            }
        } else if (DataFieldBO.FIELD_TYPE_VARCHAR.equals(field.getFieldType()) && !Constants.YES.equals(field.getEnumerate())) {
            int fieldSize = field.getFieldSize() <= 0 ? 100 : field.getFieldSize();
            if (fieldValue.toString().length() > fieldSize) {
                throw new CommonException("字段【" + field.getFieldName() + "】最大长度为：" + fieldSize + "！");
            }
        } else if (DataFieldBO.FIELD_TYPE_VARCHAR.equals(field.getFieldType())
                && Constants.YES.equals(field.getEnumerate())
                && !(DataFieldBO.ENUMERATE_TYPE_UNIT.equals(field.getEnumerateType())
                    || DataFieldBO.ENUMERATE_TYPE_ENT.equals(field.getEnumerateType())
                    || DataFieldBO.ENUMERATE_TYPE_DEPT.equals(field.getEnumerateType())
                    || DataFieldBO.ENUMERATE_TYPE_EMP.equals(field.getEnumerateType())
                    || DataFieldBO.ENUMERATE_TYPE_ROLE.equals(field.getEnumerateType()))) {
            if (Tool.isBlank(field.getEnumerateValue())) {
                throw new CommonException("字段【" + field.getFieldName() + "】未配置枚举值！");
            } else if (DataFieldBO.ENUMERATE_TYPE_MULTI.equals(field.getEnumerateType())
                    || DataFieldBO.ENUMERATE_TYPE_MULTI_DOWN.equals(field.getEnumerateType())) {
                String[] fieldValues = fieldValue.toString().trim().split(",");
                for (String value : fieldValues) {
                    if (!field.getEnumerateValue().contains(value)) {
                        throw new CommonException("字段【" + field.getFieldName() + "】" +
                                "的值必须为：" + field.getEnumerateValue() + "！");
                    }
                }
            } else if (!field.getEnumerateValue().contains(fieldValue.toString().trim())) {
                throw new CommonException("字段【" + field.getFieldName() + "】" +
                        "的值必须为：" + field.getEnumerateValue() + "！");
            }
        }
    }

    /**
     * 设置默认值，当字段有默认值，且未传值过来时设置默认值
     */
    private void updateDefaultValue(DataFieldBO field, Map<String, Object> data) {
        if (Tool.isBlank(field.getDefaultValue())) return;

        if (Tool.isBlank(data.get(field.getFieldName()))) {
            data.put(field.getFieldName(), SymbolUtil.parse(field.getDefaultValue()));
        }
    }

    /**
     * 根据数据模型id删除对应的数据模型数据
     * @param id 数据模型id
     * @param data 删除的数据模型数据
     * @return int > 0 删除成功，否则删除失败
     */
    public int deleteByDataModelId(String id, Map<String, Object> data) {
        DataModelBO dataModel = dataModelService.queryBy(id);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许删除！");

        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));

        Map<String, Object> deleteMap = SqlBuilderFactory.buildDeleteMap(deleteResolver.resolve(dataModel, data));
        int result = commonService.delete(deleteMap);
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    /**
     * 根据数据模型id删除对应的数据模型数据
     * @param modelId 数据模型id
     * @param dataId 删除的数据模型数据id
     * @return int > 0 删除成功，否则删除失败
     */
    public int deleteByModelId(String modelId, String dataId) {
        DataModelBO dataModel = dataModelService.queryBy(modelId);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许删除！");

        Map<String, Object> dataMap = new HashMap<>();
        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        dataModel.getFieldList().stream()
                .filter(field -> Constants.YES.equals(field.getPrimaryKey()))
                .findFirst()
                .ifPresent(field -> dataMap.put(field.getFieldName(), dataId));
        Map<String, Object> deleteMap = SqlBuilderFactory.buildDeleteMap(deleteResolver.resolve(dataModel, dataMap));
        int result = commonService.delete(deleteMap);
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    /**
     * 根据数据模型id删除对应的数据模型数据
     * @param code 数据模型id
     * @param dataId 删除的数据模型数据id
     * @return int > 0 删除成功，否则删除失败
     */
    public int deleteById(String code, String dataId) {
        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许删除！");

        Map<String, Object> dataMap = new HashMap<>();
        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        dataModel.getFieldList().stream()
                .filter(field -> Constants.YES.equals(field.getPrimaryKey()))
                .findFirst()
                .ifPresent(field -> dataMap.put(field.getFieldName(), dataId));
        if (dataMap.isEmpty()) throw new CommonException("数据模型主键未配置");

        Map<String, Object> deleteMap = SqlBuilderFactory.buildDeleteMap(deleteResolver.resolve(dataModel, dataMap));
        int result = commonService.delete(deleteMap);
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    public DatasourceBO getDatasource(String id) {
        return datasourceService.queryBy(id);
    }

    public int batchDelete(String code, List<Object> idList, boolean trigger) {
        DataModelBO dataModel = dataModelService.queryByCode(code);
        if (dataModel == null) throw new CommonException("数据模型信息不存在！");
        if (!Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) throw new CommonException("非库表数据模型不允许删除！");

        List<Map<String, Object>> dataListMap = new ArrayList<>();
        dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));
        dataModel.getFieldList().stream()
                .filter(field -> Constants.YES.equals(field.getPrimaryKey()))
                .findFirst()
                .ifPresent(field ->
                    idList.forEach(id -> {
                        Map<String, Object> dataMap = new HashMap<>();
                        dataMap.put(field.getFieldName(), id);
                        Map<String, Object> deleteMap = SqlBuilderFactory.buildDeleteMap(
                                deleteResolver.resolve(dataModel, dataMap));
                        if (!deleteMap.isEmpty()) {
                            dataListMap.add(deleteMap);
                        }
                    })
                );
        if (dataListMap.isEmpty()) throw new CommonException("数据模型主键未配置");

        int result = commonService.batchDelete(dataListMap, trigger);
        MessageUtil.publish(Topic.MODEL_DATA_CHANGE, dataModel.getId());
        return result;
    }

    private boolean isInsert(DataModelBO dataModel, Map<String, Object> data) {
        return isInsert(dataModel, data, false);
    }

    private boolean isInsert(DataModelBO dataModel, Map<String, Object> data, boolean isCopy) {
        DataFieldBO dataField = dataModel.getFieldList().stream()
                .filter(field -> Constants.YES.equals(field.getPrimaryKey()))
                .findFirst()
                .orElse(null);
        if (isCopy && dataField != null) {
            data.remove(dataField.getFieldName());
        }
        return dataField != null && Tool.isBlank(data.get(dataField.getFieldName()));
    }

    @SuppressWarnings("unchecked")
    public Map<String, Map<String, Object>> parsePageData(String pageId, Map<String, Object> pageData) {
        Map<String, Map<String, Object>> resultMap = new HashMap<>();
        PageBO page = pageService.queryBy(pageId);
        page.getCompList().stream().filter(item -> PageCompBO.TYPE_FORM.equals(item.getType())).forEach(pageComp -> {
            Object compData = pageData.get(pageComp.getName());
            if (compData instanceof Map) {
                resultMap.put(pageComp.getDataModelId(), (Map<String, Object>) compData);
            }
        });

        return resultMap;
    }

    @SuppressWarnings("unchecked")
    public Map<String, Map<String, Object>> saveByPageId(
            UserDetail user,
            String pageId,
            String buttonId,
            Map<String, Object> pageData,
            Map<String, Object> defaultData) {
        if (pageData == null) return null;
        Map<String, Map<String, Object>> resultMap = new HashMap<>();
        PageBO page = pageService.queryBy(pageId);
        Map<String, Object> pageParamMap = new HashMap<>(); // 页面参数
        boolean copyData;
        if (pageData.containsKey("copyData") && pageData.get("copyData") instanceof Boolean) {
            copyData = (Boolean) pageData.get("copyData");
        } else {
            copyData = false;
        }
        page.getCompList().stream().filter(item -> PageCompBO.TYPE_FORM.equals(item.getType())).forEach(pageComp -> {
            String dataModelId = pageComp.getDataModelId();
            DataModelBO dataModel = dataModelService.queryBy(dataModelId);
            dataModel.setFieldList(dataFieldService.queryListBy(dataModel.getId()));

            Object compData = pageData.get(pageComp.getName());
            if (compData instanceof Map) {
                Map<String, Object> modelData = (Map<String, Object>) compData;

                pageComp.getParamList().stream()
                        .filter(item -> PageCompParamBO.TYPE_IN.equals(item.getType()))
                        .filter(item -> PageCompParamBO.USE_TYPE_FORM.equals(item.getUseType())
                                || PageCompParamBO.USE_TYPE_ALL.equals(item.getUseType()))
                        .forEach(param ->
                                dataModel.getFieldList().forEach(field -> {
                                    if (field.getId().equals(param.getPageCompParamId())
                                            && Tool.isNotBlank(pageParamMap.get(param.getPageParamId()))) {
                                        modelData.put(field.getFieldName(), pageParamMap.get(param.getPageParamId()));
                                    }
                                }));

                if (defaultData != null) {
                    modelData.putAll(defaultData);
                }
                saveByDataModelId(dataModelId, user, modelData, buttonId, copyData);
                resultMap.put(dataModelId, modelData);

                // 输出出参数据
                pageComp.getParamList().stream()
                        .filter(item -> PageCompParamBO.TYPE_OUT.equals(item.getType()))
                        .filter(item -> PageCompParamBO.USE_TYPE_FORM.equals(item.getUseType())
                                || PageCompParamBO.USE_TYPE_ALL.equals(item.getUseType()))
                        .forEach(param ->
                                dataModel.getFieldList().forEach(field -> {
                                    if (field.getId().equals(param.getPageCompParamId())) {
                                        pageParamMap.put(param.getPageParamId(), modelData.get(field.getFieldName()));
                                    }
                                }));
            } else if (compData instanceof List) {
                List<Map<String, Object>> dataList = (List<Map<String, Object>>) compData;

                // 查询多出的数据删除
                List<List<Object>> inputParamList = new ArrayList<>();
                pageComp.getParamList().stream()
                        .filter(item -> PageCompParamBO.TYPE_IN.equals(item.getType()))
                        .filter(item -> PageCompParamBO.USE_TYPE_FORM.equals(item.getUseType())
                                || PageCompParamBO.USE_TYPE_ALL.equals(item.getUseType()))
                        .forEach(param ->
                                dataModel.getFieldList().forEach(field -> {
                                    if (field.getId().equals(param.getPageCompParamId())) {
                                        List<Object> paramList = new ArrayList<>();
                                        paramList.add(field.getFieldName());
                                        paramList.add(Condition.MATCH_MODE_EQU);
                                        paramList.add(pageParamMap.get(param.getPageParamId()));
                                        inputParamList.add(paramList);
                                    }
                                }));

                Map<String, Object> paramMap = new HashMap<>();
                paramMap.put("inputParamList", inputParamList);

                DataFieldBO dataFieldBO = dataModel.getFieldList().stream()
                        .filter(item -> Constants.YES.equals(item.getPrimaryKey()))
                        .findFirst().orElse(null);
                String pkName = dataFieldBO == null ? "" : dataFieldBO.getFieldName();

                queryList(dataModelId, paramMap).forEach(item -> {
                    Object id = item.get(pkName);
                    if (id != null && dataList.stream().noneMatch(itemData -> id.equals(itemData.get(pkName)))) {
                        deleteByDataModelId(dataModelId, item);
                    }
                });

                // 输入入参数据
                dataList.forEach(modelData ->
                        pageComp.getParamList().stream()
                                .filter(item -> PageCompParamBO.TYPE_IN.equals(item.getType())
                                        && (PageCompParamBO.USE_TYPE_FORM.equals(item.getUseType())
                                            || PageCompParamBO.USE_TYPE_ALL.equals(item.getUseType())))
                                .forEach(param ->
                                        dataModel.getFieldList().forEach(field -> {
                                            if (field.getId().equals(param.getPageCompParamId())
                                                    && Tool.isNotBlank(pageParamMap.get(param.getPageParamId()))) {
                                                modelData.put(field.getFieldName(), pageParamMap.get(param.getPageParamId()));
                                            }
                                        })));

                dataList.forEach(modelData -> saveByDataModelId(dataModelId, user, modelData, buttonId, copyData));
            }
        });

        return resultMap;
    }
}
